package com.hua.utils;

import com.alibaba.fastjson2.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

@Component
public class JwtUtils {
    // 有效期
    private static final long JWT_EXPIRE = 7*24*60 * 60 * 1000L; // 7天失效
    // 令牌秘钥
    private static final String JWT_KEY = "123456";


    /**
     * 生成JWT令牌
     * @param data
     * @return
     */
    public String createToken(Object data) {
        // 当前时间
        long currentTime = System.currentTimeMillis();
        // 过期时间
        long expTime = currentTime + JWT_EXPIRE;
        // 构建jwt
        String JWT = Jwts.builder()
                .setId(UUID.randomUUID() + "") // 设置JWT的ID
                .setSubject(JSON.toJSONString(data)) // 设置JWT的主题，将data对象转为JSON字符串
                .setIssuer("system") // 设置JWT的签发者
                .setIssuedAt(new Date(currentTime)) // 设置JWT的签发时间
                .signWith(SignatureAlgorithm.HS256, encodeSecret(JWT_KEY)) // 使用HS256算法和密钥对JWT进行签名
                .setExpiration(new Date(expTime))// 设置JWT的过期时间
                .compact(); //得到字符串的JWT令牌

        return JWT; // 返回生成的JWT字符串
    }

    /**
     * 密钥进行Base64编码，并使用编码后的密钥创建SecretKeySpec实例作为密钥
     * @param key
     * @return
     */
    private SecretKey encodeSecret(String key) {
        byte[] encode = Base64.getEncoder().encode(key.getBytes()); // 使用Base64编码对密钥进行编码
        SecretKeySpec aes = new SecretKeySpec(encode, 0, encode.length, "AES"); // 基于编码后的密钥创建SecretKeySpec实例
        return aes; // 返回SecretKeySpec实例作为密钥
    }

    /**
     *返回的是解析后的Claims对象，其中包含JWT的信息，
     * 如ID、主题、签发者、签发时间、过期时间等。可以通过调用相关方法获取相应的信息。
     * @param token
     * @return
     */
    public Claims parseToken(String token) {
        Claims body = Jwts.parser()
                .setSigningKey(encodeSecret(JWT_KEY)) // 使用密钥对token进行解析和验证
                .parseClaimsJws(token)
                .getBody(); // 获取解析后的JWT的载荷部分（Claims）
        return body; // 返回解析后的Claims对象
    }

    /**
     *方法将解析后的主题（subject）解析为指定类型的对象并返回，
     * 这里使用了FastJSON库将主题转换为指定类型的对象，并返回该对象。
     * @param token
     * @param clazz
     * @return
     * @param <T>
     */
    public <T> T parseToken(String token, Class<T> clazz) {
        Claims body = Jwts.parser()
                .setSigningKey(encodeSecret(JWT_KEY)) // 使用密钥对token进行解析和验证
                .parseClaimsJws(token)
                .getBody(); // 获取解析后的JWT的载荷部分（Claims）
        return JSON.parseObject(body.getSubject(), clazz); // 将Claims中的主题解析为指定类型的对象并返回
    }
}
